package com.middlegroup.pay.service.impl;

import com.middlegroup.common.enums.ChannelCode;
import com.middlegroup.common.enums.ServiceType;
import com.middlegroup.common.exception.ErrorMsg;
import com.middlegroup.common.model.PayRequest;
import com.middlegroup.common.model.RefundRequestDto;
import com.middlegroup.common.model.TransResult;
import com.middlegroup.pay.dto.RouterRequest;
import com.middlegroup.pay.dto.RouterResponse;
import com.middlegroup.pay.entity.InBills;
import com.middlegroup.pay.entity.RefundBills;
import com.middlegroup.pay.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.UUID;

/**
 *
 * @author pc
 * @date 2019/1/25
 */
@Service
@Slf4j
public class PayServiceImpl implements PayService {
    @Resource
    private SubjectPayService subjectPayService;
    @Resource
    private PaypalService paypalService;
    @Resource
    private InBillsService inBillsService;
    @Resource
    private RefundBillsService refundBillsService;

    @Value("${userinfo.encryptor.aeskey}")
    private String userInfoEncryptKey;

    @Resource
    private MerchantSubjectChannelRouterService merchantSubjectChannelRouterService;

    @Resource
    private WechatPayH5Service wechatPayH5Service;

    @Resource
    private AlipayService alipayService;
    @Override
    @Transactional(readOnly = false)
    public TransResult pay(PayRequest request) {
        //初始化交易结果
        TransResult transResult = new TransResult();
        transResult.setAmount(request.getAmount());
        transResult.setMerchantBillNo(request.getMerchantBillNo());
        transResult.setTransTime(System.currentTimeMillis());
        transResult.setMsg("微信，支付宝，paypal支付处理中");

        //插入订单表
        InBills inBills = new InBills();
        inBills.setMerchantBillNo(request.getMerchantBillNo());
        inBills.setAmount(request.getAmount());
        inBills.setSubjectCode(request.getSubjectCode());
        inBills.setCurrency(request.getTransCurrency());
        inBills.setNotifyUrl(request.getNotifyUrl());
        try {
            inBills.setServiceType(ServiceType.valueOf(request.getChannel()));
        } catch (Exception e) {
            transResult.setTransStatus(2);
            log.error(ErrorMsg.NO_CHANNEL, e);
            return transResult;
        }
        inBills.setMerchantCode(request.getMerchantCode());
        inBills.setStatus(0);
        String billNo = UUID.randomUUID().toString().replaceAll("-", "");
        inBills.setBillNo(billNo);
        inBills.setReturnUrl(request.getReturnUrl());
        request.setBillNo(billNo);
        boolean rt = inBillsService.insert(inBills);
        if (!rt) {
            //插入订单失败，交易失败，流程终止
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.CREATE_BILL_FAILED);
            return transResult;
        }
        transResult.setBillNo(billNo);

        //校验参数
        if (StringUtils.isBlank(request.getChannel())) {
            inBills.setStatus(2);
            inBills.setMsg("渠道 wx_h5:微信h5、wx_sdk:微信sdk、alipay_h5:支付宝h5、alipay_sdk:支付宝sdk、 paypal不能为空!");
            inBillsService.updateById(inBills);
            //插入订单失败，交易失败，流程终止
            transResult.setTransStatus(2);
            transResult.setMsg("渠道 wx_h5:微信h5、wx_sdk:微信sdk、alipay_h5:支付宝h5、alipay_sdk:支付宝sdk、 paypal不能为空!");
            return transResult;
        }

        if (StringUtils.isBlank(request.getMerchantBillNo())){
            inBills.setStatus(2);
            inBills.setMsg(ErrorMsg.EMPTY_MERCHANTBILLNO);
            inBillsService.updateById(inBills);

            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.EMPTY_MERCHANTBILLNO);
            return transResult;
        }
        if (StringUtils.isBlank(request.getBillNo())){
            inBills.setStatus(2);
            inBills.setMsg(ErrorMsg.EMPTY_BILLNO);
            inBillsService.updateById(inBills);

            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.EMPTY_BILLNO);
            return transResult;
        }
        if (StringUtils.isBlank(request.getSubjectCode())){
            inBills.setStatus(2);
            inBills.setMsg(ErrorMsg.EMPTY_SUBJECTCODE);
            inBillsService.updateById(inBills);

            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.EMPTY_SUBJECTCODE);
            return transResult;
        }

        //插入成功，往上游提单
        //路由
        RouterRequest routerRequest = new RouterRequest();
        routerRequest.setMerchantCode(request.getMerchantCode());
        routerRequest.setSubjectCode(request.getSubjectCode());

        routerRequest.setServiceType(request.getChannel());
        routerRequest.setBankCode(request.getChannel());
        RouterResponse routerResponse = null;
        try {
            routerResponse = merchantSubjectChannelRouterService.router(routerRequest);
        } catch (Exception e) {
            log.error("路由失败", e);
            inBills.setStatus(2);
            inBills.setMsg(ErrorMsg.NOT_CONFIG_ROUTER);
            inBillsService.updateById(inBills);
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.NOT_CONFIG_ROUTER);
            return transResult;
        }
        if (null == routerResponse) {
            log.error("路由失败");
            inBills.setStatus(2);
            inBills.setMsg(ErrorMsg.NOT_CONFIG_ROUTER);
            inBillsService.updateById(inBills);
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.NOT_CONFIG_ROUTER);
            return transResult;
        }
        //路由成功，选择需要发到的主体网关地址、主体编码、通道编码、交易参数等
        String gatewayUrl = routerResponse.getServiceUrl();
        if (StringUtils.isBlank(gatewayUrl)) {
            inBills.setStatus(2);
            inBills.setMsg(ErrorMsg.SUBJECT_CONFIG_NOT_COMPLETE);
            inBillsService.updateById(inBills);
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.SUBJECT_CONFIG_NOT_COMPLETE);
            return transResult;
        }
        //组装交易参数发往主体服务端处理
        request.setSubjectCode(routerResponse.getSubjectCode());
        request.setChannelCode(ChannelCode.valueOf(routerResponse.getChannelCode()));
        inBills.setChannelCode(routerResponse.getChannelCode());
        //调用subjectpay主体服务端
        /**
         * 此处一定要注意，调用第三方渠道接口必须返回TransResult，不可为空，且保证异常在接口中已处理
         */
        switch (request.getChannelCode()){
            case wx_h5:
                try{
                    //TODO 微信H5支付
//                    transResult = subjectPayService.wechatPayH5(request);
                    transResult=wechatPayH5Service.wechatPayH5(request);
                }catch (Exception e){
                    log.error("WECHANTPAYH5第三方通道微信H5支付接口调用失败"+request.getBillNo(),e);
                }
                break;
            case alipay_h5:
                try{
                    //TODO 支付宝H5支付
//                    transResult = subjectPayService.wechatPayH5(request);
                    transResult=alipayService.createAlipay(request);
                }catch (Exception e){
                    log.error("ALIPAYH5第三方通道微信H5支付接口调用失败"+request.getBillNo(),e);
                }
                break;
            case paypal:
                try{
                    //TODO paypal支付
                    transResult=paypalService.payPalPay(request);
                    inBills.setOrderId(transResult.getTransNo());//第三方返回的
                }catch (Exception e){
                    log.error("WECHANTPAYH5第三方通道微信H5支付接口调用失败"+request.getBillNo(),e);
                }
                break;
            default:
                transResult.setTransStatus(2);
                transResult.setMsg("未找到相应channelCode!");
        }

        if (null != transResult && null != transResult.getTransStatus()) {
            inBills.setStatus(transResult.getTransStatus());
            inBills.setMsg(transResult.getMsg());
//            inBills.setPayTime(System.currentTimeMillis());
            inBillsService.updateById(inBills);
        }
        if (null == transResult) {
            transResult = new TransResult();
            transResult.setAmount(request.getAmount());
            transResult.setTransStatus(0);
            transResult.setMerchantBillNo(request.getMerchantBillNo());
            transResult.setTransTime(System.currentTimeMillis());
            transResult.setMsg("微信，支付宝，paypal支付处理中");
        }
        try {
            inBillsService.updateById(inBills);
        } catch (Exception e) {
            log.error("更新订单失败:" + inBills.getMerchantBillNo(), e);
        }
        return transResult;
    }

    @Override
    @Transactional(readOnly = false)
    public TransResult refund(RefundRequestDto request) {
        //初始化交易结果
        TransResult transResult = new TransResult();
        transResult.setAmount(request.getRefundAmount());
        transResult.setMerchantBillNo(request.getMerchantBillNo());
        transResult.setTransTime(System.currentTimeMillis());
        transResult.setMsg("退款处理中");
        transResult.setBillNo(request.getBillNo());
        transResult.setTransStatus(0);
        if(!refundBillsService.getByMerchantBillNo(request.getMerchantBillNo())){
            transResult.setMsg(ErrorMsg.IN_THE_ORDERREFUND);
            return transResult;
        }

        if (StringUtils.isBlank(request.getSubjectCode())) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.EMPTY_SUBJECTCODE);
            return transResult;
        }
        if (StringUtils.isBlank(request.getMerchantCode())) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.EMPTY_MERCHANTCODE);
            return transResult;
        }

        InBills inBills= inBillsService.getByMerchantBillNo(request.getMerchantBillNo());
        if (null == inBills) {
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.BILLSNOTFOUND_OR_STATUSFAIL);
            return transResult;
        }
        if (1 != inBills.getStatus().intValue()) {
            transResult.setTransStatus(2);
            transResult.setMsg("该订单未支付成功！");
            return transResult;
        }
        if (inBills.getAmount().compareTo(request.getRefundAmount()) < 0) {
            transResult.setTransStatus(2);
            transResult.setMsg("退款金额不能大于订单金额！");
            return transResult;
        }

        //插入订单表
        RefundBills refundBills = new RefundBills();
        refundBills.setMerchantBillNo(request.getMerchantBillNo());
        refundBills.setAmount(request.getRefundAmount());
        refundBills.setServiceType(inBills.getServiceType().getCode());
        refundBills.setSubjectCode(inBills.getSubjectCode());
        refundBills.setMerchantCode(inBills.getMerchantCode());
        refundBills.setStatus(0);
        String billNo = UUID.randomUUID().toString().replaceAll("-", "");
        refundBills.setRefundNo(billNo);//自己的退款流水号
        refundBills.setMerchantRefundNo(request.getMerchantRefundNo());//商家的退款单号
        refundBills.setNotifyUrl(request.getNotifyUrl());//异步通知商家地址
        request.setBillNo(billNo);
        boolean rt = refundBillsService.insert(refundBills);
        if (!rt) {
            //插入订单失败，交易失败，流程终止
            transResult.setTransStatus(2);
            transResult.setMsg(ErrorMsg.CREATE_BILL_FAILED);
            return transResult;
        }
        transResult.setBillNo(billNo);
        //插入成功，往上游提单
        //调用subjectpay主体服务端
        switch (inBills.getServiceType()){
            case wx_h5:
                try{
                    //TODO 微信H5退款
                    transResult=wechatPayH5Service.wechatPayH5Refund(request);
                }catch (Exception e){
                    log.error("wx_h5第三方通道微信H5退款接口调用失败"+request.getBillNo(),e);
                }
                break;
            case alipay_h5:
                try{
                    //TODO 支付宝H5退款
//                    transResult = subjectPayService.wechatPayH5(request);
                    transResult=alipayService.refundAlipay(request,transResult);
                }catch (Exception e){
                    log.error("alipay_h5第三方通道支付宝H5退款接口调用失败"+request.getBillNo(),e);
                }
                break;
            case paypal:
                try{
                    //TODO paypal退款
                    transResult = paypalService.saleRefund(request,transResult);
                    refundBills.setOutRequestNo(transResult.getTransNo());
                }catch (Exception e){
                    log.error("paypal第三方通道Paypal退款接口调用失败"+request.getBillNo(),e);
                }
                break;
            default:
                transResult.setTransStatus(2);
                transResult.setMsg("未找到相应channelCode!");
        }
        if (null != transResult && null != transResult.getTransStatus()) {
            refundBills.setRefundTime(System.currentTimeMillis());
            refundBills.setStatus(transResult.getTransStatus());
            refundBills.setMsg(transResult.getMsg());
        }
        if (null == transResult) {
            transResult = new TransResult();
            transResult.setAmount(request.getRefundAmount());
            transResult.setTransStatus(0);
            transResult.setMerchantBillNo(request.getMerchantBillNo());
            transResult.setTransTime(System.currentTimeMillis());
            transResult.setMsg("退款处理中");
        }
        try {
            refundBillsService.updateById(refundBills);
        } catch (Exception e) {
            log.error("更新订单失败:" + inBills.getMerchantBillNo(), e);
        }
        return transResult;
    }
}